﻿using System;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Criterion;
using Neturion.Dados;
using Neturion.IRepositorios;

namespace Neturion.Repositorios
{
    public class RepositorioFormaPagamento : IRepositorioFormaPagamento
    {
        public FormaPagamento Inserir(FormaPagamento formaPagamento)
        {
            GerenciadorBDConfigs.Instance.SessaoAtual().Save(formaPagamento);
            return formaPagamento;
        }

        public FormaPagamento Atualizar(FormaPagamento formaPagamento)
        {
            FormaPagamento tmpFormaPagamento = ObterPorId(formaPagamento.FormaPagamentoId);
            // Atribuicao dos valores do objeto da memoria para o objeto obtido no banco de dados
            tmpFormaPagamento.Codigo = formaPagamento.Codigo;
            tmpFormaPagamento.Descricao = formaPagamento.Descricao;
            tmpFormaPagamento.EnumTipoMovimentoFinanceiro = formaPagamento.EnumTipoMovimentoFinanceiro;
            tmpFormaPagamento.TipoFormaPagamento = formaPagamento.TipoFormaPagamento;
            tmpFormaPagamento.ContaBancoVinculada = formaPagamento.ContaBancoVinculada;
            tmpFormaPagamento.Carteira = formaPagamento.Carteira;
            tmpFormaPagamento.Convenio = formaPagamento.Convenio;
            tmpFormaPagamento.Aceite = formaPagamento.Aceite;
            tmpFormaPagamento.EnumEspecieFormaPagamento = formaPagamento.EnumEspecieFormaPagamento;
            tmpFormaPagamento.DiaVencimento = formaPagamento.DiaVencimento;
            tmpFormaPagamento.LocalPagamento = formaPagamento.LocalPagamento;
            tmpFormaPagamento.ForcarVencimento = formaPagamento.ForcarVencimento;
            tmpFormaPagamento.DiaFechamento = formaPagamento.DiaFechamento;
            tmpFormaPagamento.TamanhoNossoNumero = formaPagamento.TamanhoNossoNumero;

            GerenciadorBDConfigs.Instance.SessaoAtual().Update(tmpFormaPagamento);
            return tmpFormaPagamento;
        }

        public void Excluir(FormaPagamento formaPagamento)
        {
            GerenciadorBDConfigs.Instance.SessaoAtual().Delete(formaPagamento);
        }

        public IList<FormaPagamento> ObterTodos()
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(FormaPagamento));
            return criteria.List<FormaPagamento>() as List<FormaPagamento>;
        }

        public FormaPagamento ObterPorId(int id)
        {
            return GerenciadorBDConfigs.Instance.SessaoAtual().Get<FormaPagamento>(id);
        }

        public IList<FormaPagamento> ObterTodos(
            int inicio, 
            int quantidade, 
            int quantidadeMinima, 
            string codigo, 
            string descricao,
            TipoFormaPagamento tipoFormaPagamento,
            EnumTipoMovimentoFinanceiro enumTipoMovimentoFinanceiro)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(FormaPagamento))
               .Add(Restrictions.Eq("EnumTipoMovimentoFinanceiro",enumTipoMovimentoFinanceiro))
               .SetFirstResult(inicio).SetMaxResults(quantidade);

            if (!string.IsNullOrEmpty(codigo))
            {
                criteria.Add(Restrictions.Eq("Codigo", codigo));
            }

            if (!string.IsNullOrEmpty(descricao))
            {
                criteria.Add(Restrictions.Like("Descricao", descricao, MatchMode.Anywhere));
            }

            if (tipoFormaPagamento != null)
            {
                criteria.Add(Restrictions.Eq("TipoFormaPagamento", tipoFormaPagamento));
            }

            return criteria.List<FormaPagamento>() as List<FormaPagamento>;
        }

        public IList<FormaPagamento> ObterTodos(
            string codigo,
            string descricao,
            TipoFormaPagamento tipoFormaPagamento,
            EnumTipoMovimentoFinanceiro enumTipoMovimentoFinanceiro)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual()
                .CreateCriteria(typeof (FormaPagamento))
                .Add(Restrictions.Eq("EnumTipoMovimentoFinanceiro",enumTipoMovimentoFinanceiro));

            if (!string.IsNullOrEmpty(codigo))
            {
                criteria.Add(Restrictions.Eq("Codigo", codigo));
            }

            if (!string.IsNullOrEmpty(descricao))
            {
                criteria.Add(Restrictions.Like("Descricao", descricao, MatchMode.Anywhere));
            }

            if (tipoFormaPagamento != null)
            {
                criteria.Add(Restrictions.Eq("TipoFormaPagamento", tipoFormaPagamento));
            }

            return criteria.List<FormaPagamento>() as List<FormaPagamento>;
        }

        public FormaPagamento ObterPorCodigo(string codigo)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(FormaPagamento))
                .Add(Restrictions.Eq("Codigo", codigo));

            return criteria.UniqueResult<FormaPagamento>() as FormaPagamento;
        }

        public IList<FormaPagamento> ObterPorTipo(EnumTipoFormaPagamento enumTipoFormaPagamento)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(FormaPagamento))
                .CreateAlias("TipoFormaPagamento", "TipoFormaPagamento")
                .Add(Restrictions.Eq("TipoFormaPagamento.EnumTipoFormaPagamento", enumTipoFormaPagamento))
                ;

            GenerateSQL(criteria);

            return criteria.List<FormaPagamento>() as List<FormaPagamento>;
        }

        private string GenerateSQL(ICriteria criteria)
        {
            NHibernate.Impl.CriteriaImpl criteriaImpl = (NHibernate.Impl.CriteriaImpl)criteria;
            NHibernate.Engine.ISessionImplementor session = criteriaImpl.Session;
            NHibernate.Engine.ISessionFactoryImplementor factory = session.Factory;

            NHibernate.Loader.Criteria.CriteriaQueryTranslator translator =
                        new NHibernate.Loader.Criteria.CriteriaQueryTranslator(factory, criteriaImpl, criteriaImpl.EntityOrClassName,
                                                                    NHibernate.Loader.Criteria.CriteriaQueryTranslator.RootSqlAlias);

            String[] implementors = factory.GetImplementors(criteriaImpl.EntityOrClassName);

            NHibernate.Loader.Criteria.CriteriaJoinWalker walker = new NHibernate.Loader.Criteria.CriteriaJoinWalker(
                                    (NHibernate.Persister.Entity.IOuterJoinLoadable)factory.GetEntityPersister(implementors[0]),
                                    translator, factory, criteriaImpl, criteriaImpl.EntityOrClassName, session.EnabledFilters);

            /*StreamWriter streamWriter = new StreamWriter("sql.txt");
            streamWriter.Write(walker.SqlString.ToString());
            streamWriter.Close();*/

            return walker.SqlString.ToString();
        }
    }
}